package backend

import (
	"encoding/json"
)

type MqttAction int

// C -> S
// event start
const (
	EventNone MqttAction = iota // 只是标记START，不要使用
	EventLogin
	EventLogout
)

// S -> C
// command start
const (
	CommandNone MqttAction = iota + 0x1000 // 只是标记START，不要使用
	CommandShutdown
	CommandClientLogin
	CommandUpdateInfo // update system current info
)

// S -> C
// broadcast start
const (
	BroadcastNone        MqttAction = iota + 0x2000 // 只是标记START，不要使用
	BroadcastDied                                   // will of server
	BroadcastShutdown                               // notify clients to shutdown or reboot
	BroadcastClientLogin                            // notify clients to report login info
)

var broadcasts = map[string]MqttAction{
	"clientLogin": BroadcastClientLogin,
	"shutdown":    BroadcastShutdown,
}

var commands = map[string]MqttAction{
	"shutdown": CommandShutdown,
}

// C -> S
// 	event_topic="lanmon/cs/event/"
type MqttEvent struct {
	ClientId string                 `json:"client_id"` // ip address v4
	Action   MqttAction             `json:"action"`
	Args     map[string]interface{} `json:"args,omitempty"` // args of action, MAYBE empty
}

func newMqttEvent(clientId string, action MqttAction, args map[string]interface{}) *MqttEvent {
	return &MqttEvent{
		ClientId: clientId,
		Action:   action,
		Args:     args,
	}
}

func (e *MqttEvent) fromJson(payload string) error {
	if err := json.Unmarshal([]byte(payload), e); err != nil {
		return err
	}
	return nil
}

func (e *MqttEvent) toJson() (string, error) {
	data, err := json.Marshal(e)
	if err != nil {
		return "", err
	}
	return string(data), nil
}

// Command topic template.
// S -> C
//	command_topic_template="lanmon/sc/{{ .ClientId }}/command/"
//	broadcast_topic="lanmon/sc/broadcast/"
type MqttBroadcast struct {
	Action MqttAction             `json:"action"`
	Args   map[string]interface{} `json:"args,omitempty"` // args of action, MAYBE empty
}

func newMqttBroadcast(action MqttAction, args map[string]interface{}) *MqttBroadcast {
	return &MqttBroadcast{
		Action: action,
		Args:   args,
	}
}

func (b *MqttBroadcast) fromJson(payload string) error {
	if err := json.Unmarshal([]byte(payload), b); err != nil {
		return err
	}
	return nil
}

func (b *MqttBroadcast) toJson() (string, error) {
	data, err := json.Marshal(b)
	if err != nil {
		return "", err
	}
	return string(data), nil
}

type MqttCommand struct {
	ClientId string                 `json:"-"`
	Action   MqttAction             `json:"action"`
	Args     map[string]interface{} `json:"args,omitempty"` // args of action, MAYBE empty
}

func newMqttCommand(clientId string, action MqttAction, args map[string]interface{}) *MqttCommand {
	return &MqttCommand{
		ClientId: clientId,
		Action:   action,
		Args:     args,
	}
}

func (c *MqttCommand) fromJson(payload string) error {
	if err := json.Unmarshal([]byte(payload), c); err != nil {
		return err
	}
	return nil
}

func (c *MqttCommand) toJson() (string, error) {
	data, err := json.Marshal(c)
	if err != nil {
		return "", err
	}
	return string(data), nil
}
